#pragma once
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QMouseEvent>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/octree/octree.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <vector>
#include <atomic>

#include "octree/octree.hpp"

class PointCloudWidget : public QOpenGLWidget, protected QOpenGLFunctions {
    Q_OBJECT

public:
    explicit PointCloudWidget(QWidget* parent = nullptr);
    ~PointCloudWidget();

protected:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int width, int height) override;

    // 鼠标事件处理
    void mousePressEvent(QMouseEvent* event) override;
    void mouseMoveEvent(QMouseEvent* event) override;
    void wheelEvent(QWheelEvent* event) override;

private:
    // 点云数据与空间索引
    pcl::PointCloud<pcl::PointXYZ>::Ptr m_cloud;
    Octree *m_octree;
    pcl::PointXYZ minPt, maxPt;

    // OpenGL 缓冲区
    std::vector<GLuint> m_vbos; // 每个 LOD 层次一个 VBO
    GLuint m_shaderProgram;

    // 矩阵参数
    glm::mat4 m_projection;
    glm::mat4 m_view;
    glm::mat4 m_model;

    // 相机参数
    glm::vec3 m_cameraPos = glm::vec3(0.0f, 0.0f, 10.0f);
    glm::vec3 m_cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
    glm::vec3 m_cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
    float m_yaw = -90.0f;
    float m_pitch = 0.0f;

    // 鼠标交互参数
    QPoint m_lastMousePos;
    float m_zoomSpeed = 0.1f;
    glm::vec3 m_panOffset = glm::vec3(0.0f); // 存储平移偏移量

    // 视锥体结构
    struct Frustum {
        glm::vec4 planes[6]; // 六个平面方程: ax + by + cz + d = 0
    };

    // 核心方法
    void loadPointCloud();
    Frustum extractFrustum(const glm::mat4& viewProj);
    bool isNodeInFrustum(const glm::vec3& center, float size, const Frustum& frustum);
    int selectLODLevel(const glm::vec3& nodeCenter, float nodeSize, int currentDepth);
    void uploadToVBO(const pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, GLuint& vbo);
};
